package eav_service

import (
	"context"
	"errors"
	"fmt"
	"strings"
	"time"

	"rdiot-demo/internal/eav/domain"
	"rdiot-demo/internal/eav/repository"

	"github.com/google/uuid"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

// 注意：接口定义已移动到 service/interfaces.go 文件中

// entityService 实体服务实现
type entityService struct {
	entityRepo   repository.EntityRepository
	templateRepo repository.TemplateRepository
	logger       *zap.Logger
}

// NewEntityService 创建实体服务
func NewEntityService(db *gorm.DB, logger *zap.Logger) EntityService {
	entityRepo := repository.NewEntityRepository(db)
	templateRepo := repository.NewTemplateRepository(db)
	return &entityService{
		entityRepo:   entityRepo,
		templateRepo: templateRepo,
		logger:       logger,
	}
}

// CreateEntity 创建实体
func (s *entityService) CreateEntity(ctx context.Context, req CreateEntityRequest) (*domain.Entity, error) {
	s.logger.Info("Creating entity",
		zap.String("template_id", req.TemplateID.String()),
		zap.Any("data", req.Attributes))

	// 1. 验证模板存在性
	template, err := s.templateRepo.GetByID(ctx, req.TemplateID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, fmt.Errorf("template with ID '%s' not found", req.TemplateID)
		}
		s.logger.Error("Failed to get template", zap.String("template_id", req.TemplateID.String()), zap.Error(err))
		return nil, fmt.Errorf("failed to get template: %w", err)
	}

	if !template.IsActive {
		return nil, fmt.Errorf("template '%s' is not active", req.TemplateID)
	}

	// 2. 验证实体数据
	if err := s.validateEntityData(template, req.Attributes); err != nil {
		s.logger.Error("Entity data validation failed", zap.Error(err))
		return nil, fmt.Errorf("validation failed: %w", err)
	}

	// 3. 创建实体基本信息
	entity := &domain.Entity{
		ID:         uuid.New(),
		TemplateID: req.TemplateID,
		Name:       req.Name,
		Status:     domain.EntityStatusActive,
		CreatedAt:  time.Now(),
		UpdatedAt:  time.Now(),
	}

	// 4. 保存实体到数据库
	savedEntity, err := s.entityRepo.Create(ctx, entity, req.Attributes)
	if err != nil {
		s.logger.Error("Failed to create entity", zap.Error(err))
		return nil, fmt.Errorf("failed to create entity: %w", err)
	}

	// 6. 设置返回数据
	savedEntity.Attributes = req.Attributes
	savedEntity.Template = template

	s.logger.Info("Entity created successfully",
		zap.String("entity_id", savedEntity.ID.String()),
		zap.String("template_id", req.TemplateID.String()))

	return savedEntity, nil
}

// GetEntityByID 根据ID获取实体
func (s *entityService) GetEntityByID(ctx context.Context, id uuid.UUID) (*domain.Entity, error) {
	s.logger.Debug("Getting entity", zap.String("id", id.String()))

	if strings.TrimSpace(id.String()) == "" {
		return nil, errors.New("entity ID cannot be empty")
	}

	entity, err := s.entityRepo.GetByID(ctx, id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, fmt.Errorf("entity with ID '%s' not found", id)
		}
		s.logger.Error("Failed to get entity", zap.String("id", id.String()), zap.Error(err))
		return nil, fmt.Errorf("failed to get entity: %w", err)
	}

	// 检查entity是否为nil（防御性编程）
	if entity == nil {
		return nil, fmt.Errorf("entity with ID '%s' not found", id)
	}

	// 加载模板信息
	template, err := s.templateRepo.GetByID(ctx, entity.TemplateID)
	if err != nil {
		s.logger.Error("Failed to get entity template",
			zap.String("template_id", entity.TemplateID.String()), zap.Error(err))
		// 不返回错误，只是缺少模板信息
	} else {
		entity.Template = template
	}

	return entity, nil
}

// GetEntitiesByTemplate 根据模板ID获取实体列表
func (s *entityService) GetEntitiesByTemplate(ctx context.Context, templateID uuid.UUID, page, size int) ([]*domain.Entity, int64, error) {
	s.logger.Debug("Getting entities by template", zap.String("template_id", templateID.String()))

	// 验证模板是否存在
	template, err := s.templateRepo.GetByID(ctx, templateID)
	if err != nil {
		return nil, 0, fmt.Errorf("获取模板失败: %w", err)
	}
	if template == nil {
		return nil, 0, fmt.Errorf("模板不存在: %s", templateID)
	}

	entities, total, err := s.entityRepo.GetByTemplateID(ctx, templateID, page, size)
	if err != nil {
		s.logger.Error("Failed to get entities", zap.Error(err))
		return nil, 0, fmt.Errorf("获取实体列表失败: %w", err)
	}

	s.logger.Debug("Entities queried successfully", zap.Int("count", len(entities)))
	return entities, total, nil
}

// UpdateEntity 更新实体
func (s *entityService) UpdateEntity(ctx context.Context, id uuid.UUID, req UpdateEntityRequest) (*domain.Entity, error) {
	s.logger.Info("Updating entity",
		zap.String("id", id.String()),
		zap.Any("data", req.Attributes))

	if strings.TrimSpace(id.String()) == "" {
		return nil, errors.New("entity ID cannot be empty")
	}

	// 1. 检查实体是否存在
	entity, err := s.entityRepo.GetByID(ctx, id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, fmt.Errorf("entity with ID '%s' not found", id)
		}
		return nil, fmt.Errorf("failed to get entity: %w", err)
	}

	// 2. 获取模板进行数据验证
	template, err := s.templateRepo.GetByID(ctx, entity.TemplateID)
	if err != nil {
		s.logger.Error("Failed to get template for validation",
			zap.String("template_id", entity.TemplateID.String()), zap.Error(err))
		return nil, fmt.Errorf("failed to get template: %w", err)
	}

	// 3. 验证更新数据
	if err := s.validateEntityData(template, req.Attributes); err != nil {
		return nil, fmt.Errorf("validation failed: %w", err)
	}

	// 4. 更新实体基本信息
	if name := req.Name; name != nil && *name != "" {
		entity.Name = *name
	}
	entity.UpdatedAt = time.Now()

	// 5. 更新实体和属性值
	updatedEntity, err := s.entityRepo.Update(ctx, entity, req.Attributes)
	if err != nil {
		s.logger.Error("Failed to update entity", zap.Error(err))
		return nil, fmt.Errorf("failed to update entity: %w", err)
	}

	s.logger.Info("Entity updated successfully", zap.String("id", id.String()))
	return updatedEntity, nil
}

// DeleteEntity 删除实体
func (s *entityService) DeleteEntity(ctx context.Context, id uuid.UUID) error {
	s.logger.Info("Deleting entity", zap.String("id", id.String()))

	if strings.TrimSpace(id.String()) == "" {
		return errors.New("entity ID cannot be empty")
	}

	// 1. 检查实体是否存在
	_, err := s.entityRepo.GetByID(ctx, id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return fmt.Errorf("entity with ID '%s' not found", id)
		}
		return fmt.Errorf("failed to get entity: %w", err)
	}

	// 2. 检查是否有关联引用（暂时跳过，后续可以添加）
	// TODO: 检查是否有其他实体引用此实体

	// 3. 删除实体（包括属性值）
	if err := s.entityRepo.Delete(ctx, id); err != nil {
		s.logger.Error("Failed to delete entity", zap.Error(err))
		return fmt.Errorf("failed to delete entity: %w", err)
	}

	s.logger.Info("Entity deleted successfully", zap.String("id", id.String()))
	return nil
}

// QueryEntities 复杂查询实体
func (s *entityService) QueryEntities(ctx context.Context, req QueryEntitiesRequest) ([]*domain.Entity, int64, error) {
	s.logger.Debug("Querying entities", zap.Any("criteria", req))

	// 构建查询条件
	query := repository.EntityQuery{
		TemplateID: req.TemplateID,
		Name:       req.Name,
		Page:       req.Page,
		Size:       req.Size,
	}

	// 转换属性条件
	for _, condition := range req.Conditions {
		query.Conditions = append(query.Conditions, repository.AttributeCondition{
			AttributeName: condition.AttributeName,
			Operator:      condition.Operator,
			Value:         condition.Value,
			DataType:      condition.DataType,
		})
	}

	// 转换排序条件
	for _, orderBy := range req.OrderBy {
		query.OrderBy = append(query.OrderBy, repository.OrderByClause{
			Field:     orderBy.Field,
			Direction: orderBy.Direction,
		})
	}

	entities, total, err := s.entityRepo.Query(ctx, query)
	if err != nil {
		s.logger.Error("Failed to query entities", zap.Error(err))
		return nil, 0, fmt.Errorf("failed to query entities: %w", err)
	}

	s.logger.Debug("Entities queried successfully", zap.Int("count", len(entities)))
	return entities, total, nil
}

// BatchCreateEntities 批量创建实体
func (s *entityService) BatchCreateEntities(ctx context.Context, req BatchCreateEntitiesRequest) ([]*domain.Entity, error) {
	s.logger.Info("Batch creating entities", zap.Any("request", req))

	// 验证模板是否存在
	template, err := s.templateRepo.GetByID(ctx, req.TemplateID)
	if err != nil {
		return nil, fmt.Errorf("获取模板失败: %w", err)
	}
	if template == nil {
		return nil, fmt.Errorf("模板不存在: %s", req.TemplateID)
	}

	// 准备批量数据
	entities := make([]*domain.Entity, 0, len(req.Entities))
	attributesMap := make(map[uuid.UUID]map[string]interface{})

	for _, entityData := range req.Entities {
		// 验证属性数据
		if entityData.Attributes != nil {
			if err := s.validateAttributes(template.Attributes, entityData.Attributes); err != nil {
				return nil, fmt.Errorf("实体 '%s' 属性验证失败: %w", entityData.Name, err)
			}
		}

		entityID := uuid.New()
		entity := &domain.Entity{
			ID:         entityID,
			TemplateID: req.TemplateID,
			Name:       entityData.Name,
			Status:     domain.EntityStatusActive,
			CreatedAt:  time.Now(),
			UpdatedAt:  time.Now(),
		}

		entities = append(entities, entity)
		if entityData.Attributes != nil {
			attributesMap[entityID] = entityData.Attributes
		}
	}

	// 批量创建
	createdEntities, err := s.entityRepo.BatchCreate(ctx, entities, attributesMap)
	if err != nil {
		s.logger.Error("Failed to batch create entities", zap.Error(err))
		return nil, fmt.Errorf("批量创建实体失败: %w", err)
	}

	s.logger.Info("Entities created successfully", zap.Int("count", len(createdEntities)))
	return createdEntities, nil
}

// GetEntityWithAttributes 获取实体及其所有属性值
func (s *entityService) GetEntityWithAttributes(ctx context.Context, id uuid.UUID) (*EntityWithAttributes, error) {
	s.logger.Debug("Getting entity with attributes", zap.String("id", id.String()))

	if strings.TrimSpace(id.String()) == "" {
		return nil, errors.New("entity ID cannot be empty")
	}

	// 获取实体
	entity, err := s.entityRepo.GetByID(ctx, id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, fmt.Errorf("entity with ID '%s' not found", id)
		}
		s.logger.Error("Failed to get entity", zap.String("id", id.String()), zap.Error(err))
		return nil, fmt.Errorf("failed to get entity: %w", err)
	}

	// 获取模板
	template, err := s.templateRepo.GetByID(ctx, entity.TemplateID)
	if err != nil {
		s.logger.Error("Failed to get entity template",
			zap.String("template_id", entity.TemplateID.String()), zap.Error(err))
		// 不返回错误，只是缺少模板信息
	} else {
		entity.Template = template
	}

	// 获取属性值
	attributes, err := s.entityRepo.GetAttributes(ctx, id)
	if err != nil {
		s.logger.Error("Failed to get entity attributes", zap.Error(err))
		return nil, fmt.Errorf("failed to get entity attributes: %w", err)
	}

	return &EntityWithAttributes{
		Entity:     entity,
		Template:   template,
		Attributes: attributes,
		CreatedAt:  entity.CreatedAt,
		UpdatedAt:  entity.UpdatedAt,
	}, nil
}

// validateEntityData 验证实体数据
func (s *entityService) validateEntityData(template *domain.EntityTemplate, data map[string]interface{}) error {
	// 构建属性模板映射
	attrMap := make(map[string]*domain.AttributeTemplate)
	for i := range template.Attributes {
		attr := &template.Attributes[i]
		attrMap[attr.Name] = attr
	}

	// 验证必填属性
	for _, attr := range template.Attributes {
		if attr.Required {
			value, exists := data[attr.Name]
			if !exists || value == nil || (fmt.Sprintf("%v", value) == "") {
				return fmt.Errorf("required attribute '%s' is missing or empty", attr.Name)
			}
		}
	}

	// 验证属性类型和值
	for name, value := range data {
		attr, exists := attrMap[name]
		if !exists {
			// 可以选择忽略未定义的属性，或者返回错误
			s.logger.Warn("Unknown attribute", zap.String("attribute", name))
			continue
		}

		if err := s.validateAttributeValue(*attr, value); err != nil {
			return fmt.Errorf("attribute '%s' validation failed: %w", name, err)
		}
	}

	return nil
}

// validateAttributeValue 验证属性值
func (s *entityService) validateAttributeValue(attr domain.EntityAttribute, value interface{}) error {
	switch attr.DataType {
	case "string":
		if _, ok := value.(string); !ok {
			return fmt.Errorf("期望字符串类型，实际类型: %T", value)
		}
	case "number":
		switch value.(type) {
		case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
			// 数值类型正确
		default:
			return fmt.Errorf("期望数值类型，实际类型: %T", value)
		}
	case "boolean":
		if _, ok := value.(bool); !ok {
			return fmt.Errorf("期望布尔类型，实际类型: %T", value)
		}
	case "datetime":
		switch v := value.(type) {
		case string:
			if _, err := time.Parse(time.RFC3339, v); err != nil {
				return fmt.Errorf("日期时间格式错误，应为RFC3339格式: %w", err)
			}
		case time.Time:
			// 时间类型正确
		default:
			return fmt.Errorf("期望日期时间类型（字符串或时间），实际类型: %T", value)
		}
	case "reference":
		switch v := value.(type) {
		case string:
			if _, err := uuid.Parse(v); err != nil {
				return fmt.Errorf("引用ID格式错误: %w", err)
			}
		case uuid.UUID:
			// UUID类型正确
		default:
			return fmt.Errorf("期望UUID类型，实际类型: %T", value)
		}
	case "array":
		// 数组可以是任何切片类型
		// TODO: 可以进一步验证数组元素类型
	case "json":
		// JSON可以是任何复杂类型
		// TODO: 可以验证JSON结构
	default:
		return fmt.Errorf("不支持的数据类型: %s", attr.DataType)
	}

	return nil
}

// validateAttributes 验证属性数据
func (s *entityService) validateAttributes(templateAttrs []domain.EntityAttribute, attributes map[string]interface{}) error {
	// 创建属性定义映射
	attrMap := make(map[string]domain.EntityAttribute)
	for _, attr := range templateAttrs {
		attrMap[attr.Name] = attr
	}

	// 验证每个属性
	for name, value := range attributes {
		attr, exists := attrMap[name]
		if !exists {
			return fmt.Errorf("未定义的属性: %s", name)
		}

		// 验证必填属性
		if attr.Required && (value == nil || value == "") {
			return fmt.Errorf("属性 '%s' 是必填的", name)
		}

		// 跳过空值验证
		if value == nil {
			continue
		}

		// 根据数据类型验证值
		if err := s.validateAttributeValue(attr, value); err != nil {
			return fmt.Errorf("属性 '%s' 验证失败: %w", name, err)
		}
	}

	// 检查必填属性是否都提供了
	for _, attr := range templateAttrs {
		if attr.Required {
			if _, provided := attributes[attr.Name]; !provided {
				return fmt.Errorf("缺少必填属性: %s", attr.Name)
			}
		}
	}

	return nil
}
